﻿#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include <QPlainTextEdit>
#include <QPaintEvent>
#include <QContextMenuEvent>
#include <QMouseEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QTextBlock>
#include <QFontMetrics>
#include <QTextCursor>
#include <QTextBlockFormat>
#include <QTextDocument>
#include <QTextCodec>
#include <QMenu>
#include <QScrollBar>

QString GetQString(QByteArray byteArray);//防止乱码
enum TagType
{
    NUMBER=0,
    MARKROUND,//圆
    MARKBLOCK //方块
};

class TagLineNumberArea;
class  TagDataItem
{
public:
    TagDataItem(TagType tagTypeTmp, int widthTmp = 20):
        tagType(tagTypeTmp), width(widthTmp)
    {
    }
    bool BLineNumbersMark(int number)
    {
        //return std::find(vecLineNumbersMark.begin(), vecLineNumbersMark.end(),number) != vecLineNumbersMark.end();
        return mapMarkLineColor.find(number) != mapMarkLineColor.end();
    }
    void markerAdd(int line, QColor color=Qt::black)
    {
        mapMarkLineColor[line] = color;
    }
    QColor getLineColor(int line)
    {
        return mapMarkLineColor[line];
    }
    TagType tagType;
    int positionX;
    int width;
private:
    std::map<int, QColor> mapMarkLineColor;
};


class CodeEditor:public QPlainTextEdit
{
    Q_OBJECT
public:
    CodeEditor(QWidget *paren=0);
    ~CodeEditor();

    virtual void PaintTag(QPainter& painter, int line, int y);

    void AddTag(TagDataItem* item);//添加标记或行号

    void UpdateColor(int line, int startIndex, int endIndex, QColor fontColor, QColor backColor);
    void UpdateColor(int startLine, int endLine, int startColumn, int endColumn, QColor fontColor, QColor backColor);//更新行字体或背景色

    void UpdateLineNumberWidth(int lineNumberWidthNew);//更新行号宽度
    void UpdateTagWidth(int lineNumberWidthOld, int lineNumberWidth);//更新行号后面宽度

    void GoToLine(int line);//跳转至行

    int GetLineNumber(QTextCursor &cursor);//获取行号

    void lineNumberAreaPaintEvent(QPaintEvent* event);//绘制
    int lineNumberAreaWidth();//计算行号宽度
protected:
    virtual void resizeEvent(QResizeEvent *event)override;
private slots:
    void updateLineNumberAreaWidth(int newBlockCount);
    void hightlightCurrentLine();
    void updateLineNumberArea(const QRect &rect, int dy);
    void updateLineNumber();
public:
    TagLineNumberArea *tagLineNumberArea;
    int currentLineNumber;
    int currentLinePositionY;

    std::vector<TagDataItem*> vecTagDataItem;
    QColor backgroundColor;
    QColor fontColor;
    QColor fontCurrentColor;
    int lineNumberPositionX;
    int lineNumberWidth;
    int tagCurrentWidth;
    int spacing;
    bool bLineNumber;
    bool bHightCurrentLineNumber;
};

class TagLineNumberArea: public QWidget
{
public:
    TagLineNumberArea(CodeEditor *editor):QWidget(editor), codeEditor(editor)
    {

    }

    QSize sizeHint()const override
    {
        return QSize(codeEditor->lineNumberAreaWidth(), 0);
    }
protected:
    void paintEvent(QPaintEvent* event)override
    {
        codeEditor->lineNumberAreaPaintEvent(event);
    }
public:
    CodeEditor* codeEditor;
};

#endif // CODEEDITOR_H
